﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;

namespace K_Means
{
	public partial class Main : Form
	{
		private Preprocess _pre;
		private bool _type = true;
		private bool[] _ignore;
		private IgnoreAttributes _ignoreAttributes;
		private K_Means _kmeans;
		public Main()
		{
			InitializeComponent();
		}

		private void _bntOpen_Click(object sender, EventArgs e)
		{
			if (this._opeOpen.ShowDialog() == DialogResult.OK)
			{
				ReadCSV(this._opeOpen.FileName);
			}
		}

		private void ReadCSV(String name)
		{
			this._pre = new Preprocess(name);
			this._ignore = new bool[this._pre.Attributes.Length];
			if (this._lvAttributes.Items.Count > 0) this._lvAttributes.Items.Clear();
			this._lblType.Text = "Type:";
			this._lblMissing.Text = "Missing:";
			this._lblDistinct.Text = "Distinct";
			this._lblUnique.Text = "Unique";
			for (int i = 0; i < this._pre.Attributes.Length; i++) this._lvAttributes.Items.Add(new ListViewItem(new string[] { i.ToString(), this._pre.Attributes[i] }));
			if (this._lvAttributes.SelectedIndices.Count > 0) this._lvAttributes.SelectedIndices.Clear();
			this._lvAttributes.SelectedIndices.Add(0);
			foreach (ColumnHeader ch in this._lvAttributes.Columns)
			{
				ch.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
			}
		}

		private void _lvAttributes_SelectedIndexChanged(object sender, EventArgs e)
		{
			try
			{
				if (this._lvAttributes.SelectedItems.Count != 0)
				{
					int index = this._lvAttributes.SelectedItems[0].Index;
					this._lblType.Text = String.Format("Type: {0}.", this._pre.AttributeDetails[index].Type ? "Nominal" : "Number");
					int missing = this._pre.AttributeDetails[index].Missing;
					double perMissing = (double)missing / this._pre.Properties.Count;
					this._lblMissing.Text = String.Format("Missing: {0} ({1:0.000}%)", missing, perMissing);
					this._lblDistinct.Text = String.Format("Distinct: {0}", this._pre.AttributeDetails[index].Labels.Count);

					if (this._pre.AttributeDetails[index].Type)
					{
						this._lvAttributeDetails.Items.Clear();
						if (!this._type)
						{
							var _chNo = new ColumnHeader();
							_chNo.Text = "No.";
							var _chLabel = new ColumnHeader();
							_chLabel.Text = "Label";
							var _chCount = new ColumnHeader();
							_chCount.Text = "Count";
							this._lvAttributeDetails.Columns.Clear();
							this._lvAttributeDetails.Columns.AddRange(new ColumnHeader[] { _chNo, _chLabel, _chCount });
						}
						this._type = true;
						int i = 1;
						int unique = 0;
						foreach (KeyValuePair<string, int> pair in this._pre.AttributeDetails[index].Labels)
						{
							this._lvAttributeDetails.Items.Add(new ListViewItem(new string[] { i.ToString(), pair.Key, pair.Value.ToString() }));
							i++;
							if (pair.Value == 1) unique++;
						}
						double perUnique = (double)unique * 100 / this._pre.Properties.Count;
						this._lblUnique.Text = String.Format("Unique: {0} ({1:0.000}%)", unique, perUnique);
					}
					else
					{
						this._lvAttributeDetails.Items.Clear();
						if (this._type)
						{
							var _chStatistic = new ColumnHeader();
							_chStatistic.Text = "Statistic";
							var _chValue = new ColumnHeader();
							_chValue.Text = "Value";
							this._lvAttributeDetails.Columns.Clear();
							this._lvAttributeDetails.Columns.AddRange(new ColumnHeader[] { _chStatistic, _chValue });
						}
						this._type = false;
						this._lvAttributeDetails.Items.Add(new ListViewItem(new string[] { "Minimum", this._pre.AttributeDetails[index].Minimum.ToString("0.000") }));
						this._lvAttributeDetails.Items.Add(new ListViewItem(new string[] { "Maximum", this._pre.AttributeDetails[index].Maximum.ToString("0.000") }));
						this._lvAttributeDetails.Items.Add(new ListViewItem(new string[] { "Mean", this._pre.AttributeDetails[index].Mean.ToString("0.000") }));
						this._lvAttributeDetails.Items.Add(new ListViewItem(new string[] { "Standard Deviation", this._pre.AttributeDetails[index].StandardDeviation.ToString("0.000") }));
						int unique = 0;
						foreach (KeyValuePair<string, int> pair in this._pre.AttributeDetails[index].Labels)
						{
							if (pair.Value == 1) unique++;
						}
						double perUnique = (double)unique * 100 / this._pre.Properties.Count;
						this._lblUnique.Text = String.Format("Unique: {0} ({1:0.000}%)", unique, perUnique);
					}
					this._lvAttributeDetails.Columns[1].AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.ToString());
			}

		}

		private void _btnIgnoreAttributes_Click(object sender, EventArgs e)
		{
			if (this._ignoreAttributes == null)
			{
				this._ignoreAttributes = new IgnoreAttributes();
				this._ignoreAttributes.ChangeIgnoreAttributes += new EventHandler<ChangeIgnoreAtrributesEventArgs>(_ignoreAttributes_ChangeIgnoreAttributes);
				
			}
			this._ignoreAttributes.Attributes = this._pre.Attributes;
			this._ignoreAttributes.ShowDialog(this);
		}

		public void _ignoreAttributes_ChangeIgnoreAttributes(object sender, ChangeIgnoreAtrributesEventArgs e)
		{
			for (int i = 0; i < this._ignore.Length; i++) this._ignore[i] = false;
			for (int i = 0; i < e.Atrributes.Count; i++) this._ignore[e.Atrributes[i]] = true;
		}

		private void _btnStart_Click(object sender, EventArgs e)
		{
			this._kmeans = new K_Means();
			this._kmeans.NumClusters = (int)this._nudClusters.Value;
			this._kmeans.MaxIterations = (int)this._nudMaxIterations.Value;
			for (int i = 0; i < this._ignore.Length; i++)
			{
				if (!this._pre.AttributeDetails[i].Type && !this._ignore[i])
				{
					this._kmeans.AttributeDetails.Add(this._pre.AttributeDetails[i]);
				}
			}
			this._kmeans.Init();
			this._kmeans.Start();
			#region
			if (this._lvOutputs.Items.Count > 0) this._lvOutputs.Items.Clear();
			if (this._lvOutputs.Columns.Count > 0) this._lvOutputs.Columns.Clear();
			var _chName = new ColumnHeader();
			_chName.Text = "Name";
			_chName.TextAlign = HorizontalAlignment.Center;
			_chName.Name = "_chAttibutes";
			this._lvOutputs.Columns.Add(_chName);
			for (int i = 0; i < this._kmeans.NumClusters; i++)
			{
				var _chCluster = new ColumnHeader();
				_chCluster.Text = String.Format("Cluster {0}", i);
				_chCluster.TextAlign = HorizontalAlignment.Right;
				_chCluster.Name = String.Format("_chCluster{0}", i);
				this._lvOutputs.Columns.Add(_chCluster);
			}
			#endregion
			#region
			int j = 0;
			string[] subItems = new string[this._kmeans.NumClusters + 1];
			for (int i = 0; i < this._pre.AttributeDetails.Length; i++)
			{
				if (!this._ignore[i])
				{
					subItems[0] = this._pre.Attributes[i];
					if (this._pre.AttributeDetails[i].Type)
					{
						int[,] counts = new int[this._pre.AttributeDetails[i].Labels.Count, this._kmeans.NumClusters];
						Dictionary<string, int> values = new Dictionary<string, int>();
						int k = 0;
						foreach (KeyValuePair<string, int> pair	in this._pre.AttributeDetails[i].Labels)
						{
							values.Add(pair.Key, k++);
						}
						for (k = 0; k < this._kmeans.Members.Length; k++)
						{
							counts[values[this._pre.Properties[k][i]], this._kmeans.Members[k]]++;
						}
						for (k = 0; k < this._kmeans.NumClusters; k++)
						{
							int max = int.MinValue;
							foreach (KeyValuePair<string, int> pair in values)
							{
								if (max < counts[pair.Value, k])
								{
									max = counts[pair.Value, k];
									subItems[k + 1] = pair.Key;
								}
							}
						}
					}
					else
					{
						for (int k = 0; k < this._kmeans.Centers.Count; k++)
						{
							subItems[k + 1] = this._kmeans.Centers[k][j].ToString("0.000");
						}
						j++;
					}
					this._lvOutputs.Items.Add(new ListViewItem(subItems));					
				}
			}
			#endregion
			int[] _counts = new int[this._kmeans.Members.Length];
			for (int i = 0; i < this._kmeans.Members.Length; i++) _counts[this._kmeans.Members[i]]++;
			subItems[0] = "Instances";
			for (int i = 0; i < this._kmeans.NumClusters; i++)
			{
				subItems[i + 1] = String.Format("{0}({1:0.000}%)", _counts[i], (double)_counts[i] * 100 / this._kmeans.Members.Length);
			}
			this._lvOutputs.Items.Add(new ListViewItem(subItems));
			foreach (ColumnHeader ch in this._lvOutputs.Columns)
			{
				ch.AutoResize(ColumnHeaderAutoResizeStyle.ColumnContent);
			}
			
		}
	}
}
